package com.cskaoyan.gateway.controller.promotion;

import com.alibaba.fastjson.JSON;
import com.cskaoyan.gateway.cache.CacheManager;
import com.cskaoyan.gateway.form.secondskill.CreatePromoOrderInfo;
import com.google.common.util.concurrent.RateLimiter;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.promo.PromoService;
import com.mall.promo.constant.PromoRetCode;
import com.mall.promo.dto.*;
import com.mall.user.annotation.Anoymous;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @author Xiao Fan
 * @Description: 秒杀控制层
 * @date 2021/7/27 13:21
 */
@Slf4j
@RestController
@RequestMapping("/shopping")
@Api(tags = "PromoController", description = "秒杀控制层")
public class PromoController {
    @Reference(timeout = 3000, check = false)
    private PromoService promoService;

    @Autowired
    CacheManager cacheManager;

    //引入令牌桶限流，限制单位秒进入服务的请求数量
    //todo 没跟上在哪写限制数量
    RateLimiter rateLimiter;

    //引入线程池队列泄洪，限制下游服务同时处理的请求数量
    ExecutorService executorService;
    @PostConstruct
    public void init(){
        rateLimiter = RateLimiter.create(100);
        //这里不可以用new cacheThreadPool,他会创建新的线程，newFixedThreadPool会限制线程数量，到达上限后不会创建新的线程
        executorService = Executors.newFixedThreadPool(100);
    }



    /**
     * 获取秒杀列表
     *
     * @param sessionId 场次id
     * @return
     */
    @GetMapping("/seckilllist")
    @Anoymous
    public ResponseData<?> getPromoList(Integer sessionId) {
        PromoInfoRequest promoInfoRequest = new PromoInfoRequest();
        promoInfoRequest.setSessionId(sessionId);
        promoInfoRequest.setYyyymmdd(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        PromoInfoResponse promoInfoResponse = promoService.getPromoList(promoInfoRequest);
        if (PromoRetCode.SUCCESS.getCode().equals(promoInfoResponse.getCode()))
            return new ResponseUtil<>().setData(promoInfoResponse);
        return new ResponseUtil<>().setErrorMsg(promoInfoResponse.getMsg());
    }

    /**
     * 分布式秒杀下单
     *
     * @param
     * @return
     */
    @PostMapping("/seckill")
    public ResponseData<?> createPromoOrder(@RequestBody CreatePromoOrderInfo createPromoOrderInfo, HttpServletRequest request) {
        //获取令牌
        //获取成功向下执行，获取不到就等待
        rateLimiter.acquire(100);


        String userInfo = (String) request.getAttribute("userInfo");
        Map<String, Object> parse = (Map<String, Object>) JSON.parse(userInfo);
        Long uid = Long.valueOf(parse.get("uid").toString());

        //先从redis中查看商品是否售罄,售罄后直接返回
        Long psId = createPromoOrderInfo.getPsId();
        Long productId = createPromoOrderInfo.getProductId();
        String key = "stock_is_null"+psId+productId;
        String s = cacheManager.checkCache(key);
        if (s!=null&&"stockIsNullKey".equals(s.trim())){
            return new ResponseUtil<>().setErrorMsg("商品售罄");
        }

        CreatePromoOrderRequest createPromoOrderRequest = new CreatePromoOrderRequest();
        createPromoOrderRequest.setProductId(createPromoOrderInfo.getProductId());
        createPromoOrderRequest.setPsId(createPromoOrderInfo.getPsId());
        createPromoOrderRequest.setUserId(uid);
        createPromoOrderRequest.setUsername(createPromoOrderInfo.getUserName());
        createPromoOrderRequest.setAddressId(createPromoOrderInfo.getAddressId());
        createPromoOrderRequest.setTel(createPromoOrderInfo.getTel());
        createPromoOrderRequest.setStreetName(createPromoOrderInfo.getStreetName());
        //线程池异步执行任务，执行不完就缓存在线程池
        Future<CreatePromoOrderResponse> submit = executorService.submit(new Callable<CreatePromoOrderResponse>() {
            @Override
            public CreatePromoOrderResponse call() throws Exception {
                return promoService.createPromoOrderInTransaction(createPromoOrderRequest);
            }
        });


        /**
         * 不使用，使用线程池异步操作
         */
        //CreatePromoOrderResponse createPromoOrderResponse = promoService.createPromoOrderInTransaction(createPromoOrderRequest);



        //通过线程执行结果获取返回值
        CreatePromoOrderResponse createPromoOrderResponse = null;
        try {
            createPromoOrderResponse = submit.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        if (PromoRetCode.SUCCESS.getCode().equals(createPromoOrderResponse.getCode()))
            return new ResponseUtil<>().setData(createPromoOrderResponse);
        return new ResponseUtil<>().setErrorMsg(createPromoOrderResponse.getMsg());
    }

    /**
     * 获取秒杀商品详情
     *
     * @param
     * @return
     */
    @PostMapping("/promoProductDetail")
    public ResponseData<?> getPromoProductDetail(@RequestBody PromoProductDetailRequest promoProductDetailRequest) {
        PromoProductDetailResponse promoProductDetailResponse = promoService.getPromoProductDetail(promoProductDetailRequest);

        if (PromoRetCode.SUCCESS.getCode().equals(promoProductDetailResponse.getCode()))
            return new ResponseUtil<>().setData(promoProductDetailResponse);
        return new ResponseUtil<>().setErrorMsg(promoProductDetailResponse.getMsg());
    }


}
